/*
 * Copyright (c) 2024 Huawei Technologies Co., Ltd.
 * openUBMC is licensed under Mulan PSL v2.
 * You can use this software according to the terms and conditions of the Mulan PSL v2.
 * You may obtain a copy of Mulan PSL v2 at:
 *         http://license.coscl.org.cn/MulanPSL2
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 * See the Mulan PSL v2 for more details.
 */

#include <gtest/gtest.h>
#include <devmon/driver_abi.h>
#include <mc/engine.h>
#include <test_utilities/test_base.h>
#include <mc/common.h>
#include <dlfcn.h>
#include <unordered_map>
#include <memory>

#include "../../../drivers/scanner/scanner/scanner.h"
#include "../test_utils/root_object.h"

using namespace dev;
using namespace devmon;

namespace drivers {
namespace scanner {
namespace test {

// Service stub
class scanner_test_service : public mc::engine::service {
public:
    scanner_test_service(const std::string& name) : mc::engine::service(name) {}
};

// Test fixture
class ScannerAbiTest : public mc::test::TestWithEngine {
protected:
    static void SetUpTestSuite() {
        TestWithEngine::SetUpTestSuite();
        m_test_service = std::make_unique<scanner_test_service>("bmc.openubmc.test_scanner");
        m_test_service->init();
        m_test_service->start();

        // 创建根对象
        m_root_object = root_object::create_root_object(m_test_service.get());

        load_driver();
    }

    static void TearDownTestSuite() {
        m_test_service->stop();
        m_root_object.reset();
        
        // 清理设备容器，避免引用已关闭的动态库
        m_devices.clear();

        // 不手动dlclose，避免静态对象析构时访问已卸载的动态库导致SIGSEGV
        // 让系统在程序退出时自动卸载动态库
        m_test_service.reset();
        TestWithEngine::TearDownTestSuite();
    }

    void SetUp() override {}
    void TearDown() override {}

    // Driver loading (dlopen + dlsym)
    static void load_driver() {
        m_driver_handle = dlopen("./opt/bmc/drivers/libScanner.so", RTLD_LAZY);
        ASSERT_NE(m_driver_handle, nullptr) << "dlopen failed: " << dlerror();

        register_device_driver_func func = reinterpret_cast<register_device_driver_func>(
            dlsym(m_driver_handle, "register_device_driver"));
        ASSERT_TRUE(func != nullptr) << "dlsym failed: " << dlerror();

        device_driver_t* devices = nullptr;
        uint8_t count = 0;
        status_t ret = func(&devices, &count);
        ASSERT_EQ(ret, STATUS_OK);

        m_devices.clear();
        m_devices.reserve(count);
        for (uint8_t i = 0; i < count; ++i) {
            auto dev = std::make_shared<device_driver_t>(devices[i]);
            m_devices.emplace(dev->device_name, dev);
        }
    }

    // 构造测试用连接器对象
    mc::dict create_test_connector() {
        return mc::dict{{"SystemId", 1}};
    }

    // 构造测试用CSR对象
    mc::mutable_dict create_test_csr_object(const std::string& chip_path = "#/MockChip",
                                            uint32_t offset = 0x100,
                                            uint8_t size = 4,
                                            uint8_t mask = 0xFF,
                                            uint8_t type = 1,
                                            uint32_t period = 1000) {
        return mc::mutable_dict{{"Chip", chip_path}, {"Offset", offset}, {"Size", size},
                                {"Mask", mask}, {"Type", type}, {"Period", period}};
    }

    // 测试服务
    static std::unique_ptr<scanner_test_service> m_test_service;
    // 驱动符号表
    static std::unordered_map<std::string, std::shared_ptr<device_driver_t>> m_devices;
    static void* m_driver_handle;
    static root_object_ptr m_root_object;
};

std::unique_ptr<scanner_test_service> ScannerAbiTest::m_test_service;
std::unordered_map<std::string, std::shared_ptr<device_driver_t>> ScannerAbiTest::m_devices;
void* ScannerAbiTest::m_driver_handle = nullptr;
root_object_ptr ScannerAbiTest::m_root_object;

// ----- 驱动注册、结构完整性 -----
TEST_F(ScannerAbiTest, DriverRegistrationAndStructure) {
    // 驱动包含Scanner类型
    EXPECT_EQ(m_devices.size(), 1);
    EXPECT_TRUE(m_devices.count("Scanner") > 0);

    // 结构完整性
    for (const auto& kv : m_devices) {
        EXPECT_FALSE(std::string(kv.second->device_name).empty());
        EXPECT_TRUE(kv.second->ctor != nullptr);
        EXPECT_TRUE(kv.second->init != nullptr);
        EXPECT_TRUE(kv.second->start != nullptr);
        EXPECT_TRUE(kv.second->stop != nullptr);
    }
}

// ----- create 异常与空参数 -----
TEST_F(ScannerAbiTest, CreateInvalidArgsReturnNull) {
    auto drv = m_devices["Scanner"];
    ASSERT_TRUE(drv != nullptr);

    // 空服务指针
    EXPECT_EQ(drv->ctor(nullptr, "test_scanner"), nullptr);

    // 空名称指针
    EXPECT_EQ(drv->ctor(m_test_service.get(), nullptr), nullptr);

    // 两个参数都为空
    EXPECT_EQ(drv->ctor(nullptr, nullptr), nullptr);
}

// ----- create 正常分支 -----
TEST_F(ScannerAbiTest, CreateEachDeviceSuccess) {
    auto drv = m_devices["Scanner"];
    ASSERT_TRUE(drv != nullptr);

    void* instance = drv->ctor(m_test_service.get(), "test_scanner_create");
    ASSERT_NE(instance, nullptr);

    // 验证创建的对象是Scanner类型
    Scanner* scanner_device = static_cast<Scanner*>(instance);
    EXPECT_TRUE(scanner_device != nullptr);
}

// ----- create/init/start/stop 主流程&异常 ----
TEST_F(ScannerAbiTest, FullLifecycleNormalAndError) {
    auto drv = m_devices["Scanner"];
    ASSERT_TRUE(drv != nullptr);

    // 正常创建
    void* inst = drv->ctor(m_test_service.get(), "full_lifecycle_scanner");
    ASSERT_NE(inst, nullptr);

    // init 异常参数测试
    mc::mutable_dict config = create_test_csr_object();
    mc::dict conn = create_test_connector();

    // 空设备指针
    status_t ret = drv->init(nullptr, &config, &conn);
    EXPECT_EQ(ret, STATUS_ERROR);

    // 空CSR对象指针
    ret = drv->init(inst, nullptr, &conn);
    EXPECT_EQ(ret, STATUS_ERROR);

    // 空连接器指针
    ret = drv->init(inst, &config, nullptr);
    EXPECT_EQ(ret, STATUS_ERROR);

    // 正常init（可能会失败，因为需要有效的Chip引用，但这是正常的）
    ret = drv->init(inst, &config, &conn);
    // init可能会成功或失败，取决于Chip引用是否有效
    EXPECT_TRUE(ret == STATUS_OK || ret == STATUS_ERROR);

    // start 异常参数测试
    ret = drv->start(nullptr);
    EXPECT_EQ(ret, STATUS_ERROR);

    // 如果init成功，测试正常start
    if (drv->init(inst, &config, &conn) == STATUS_OK) {
        ret = drv->start(inst);
        // start可能会成功或失败，取决于初始化状态
        EXPECT_TRUE(ret == STATUS_OK || ret == STATUS_ERROR);

        // 正常stop
        ret = drv->stop(inst);
        EXPECT_EQ(ret, STATUS_OK);
    }

    // stop 异常参数测试
    ret = drv->stop(nullptr);
    EXPECT_EQ(ret, STATUS_ERROR);
}

// ----- 多实例批量测试 -----
TEST_F(ScannerAbiTest, MultiInstanceMultiType) {
    auto drv = m_devices["Scanner"];
    ASSERT_TRUE(drv != nullptr);

    std::vector<void*> instances;
    // 创建多个实例
    for (int i = 0; i < 3; ++i) {
        void* handle = drv->ctor(m_test_service.get(), ("scanner_" + std::to_string(i)).c_str());
        EXPECT_NE(handle, nullptr);
        if (handle != nullptr) {
            instances.push_back(handle);
        }
    }

    // 验证所有实例都是有效的
    EXPECT_EQ(instances.size(), 3);
    for (auto* inst : instances) {
        Scanner* scanner = static_cast<Scanner*>(inst);
        EXPECT_NE(scanner, nullptr);
    }
}

// ----- 属性基本校验（类型正确即可） -----
TEST_F(ScannerAbiTest, BasicObjectSanity) {
    auto drv = m_devices["Scanner"];
    ASSERT_TRUE(drv != nullptr);

    void* scanner_obj = drv->ctor(m_test_service.get(), "scanner_obj");
    EXPECT_NE(scanner_obj, nullptr);

    // 验证对象可以被转换为Scanner类型
    Scanner* scanner = static_cast<Scanner*>(scanner_obj);
    EXPECT_NE(scanner, nullptr);
}

// ----- init 边界值测试 -----
TEST_F(ScannerAbiTest, InitBoundaryValues) {
    auto drv = m_devices["Scanner"];
    ASSERT_TRUE(drv != nullptr);

    void* inst = drv->ctor(m_test_service.get(), "boundary_test_scanner");
    ASSERT_NE(inst, nullptr);

    mc::dict conn = create_test_connector();

    // 测试最小值
    mc::mutable_dict config_min = create_test_csr_object("#/MockChip", 0, 1, 0, 0, 1);
    status_t ret = drv->init(inst, &config_min, &conn);
    // 可能会失败，因为需要有效的Chip引用
    EXPECT_TRUE(ret == STATUS_OK || ret == STATUS_ERROR);

    // 创建新实例测试最大值（使用合理的period值）
    void* inst_max = drv->ctor(m_test_service.get(), "boundary_test_scanner_max");
    ASSERT_NE(inst_max, nullptr);

    mc::mutable_dict config_max = create_test_csr_object("#/MockChip", 0xFFFFFFFF, 8, 0xFF, 0xFF, 10000);
    ret = drv->init(inst_max, &config_max, &conn);
    EXPECT_TRUE(ret == STATUS_OK || ret == STATUS_ERROR);
}

// ----- start/stop 多次调用测试 -----
TEST_F(ScannerAbiTest, MultipleStartStop) {
    auto drv = m_devices["Scanner"];
    ASSERT_TRUE(drv != nullptr);

    void* inst = drv->ctor(m_test_service.get(), "multiple_start_stop_scanner");
    ASSERT_NE(inst, nullptr);

    mc::mutable_dict config = create_test_csr_object();
    mc::dict conn = create_test_connector();

    // 初始化
    if (drv->init(inst, &config, &conn) == STATUS_OK) {
        // 多次启动和停止
        for (int i = 0; i < 3; ++i) {
            status_t start_ret = drv->start(inst);
            EXPECT_TRUE(start_ret == STATUS_OK || start_ret == STATUS_ERROR);

            status_t stop_ret = drv->stop(inst);
            EXPECT_EQ(stop_ret, STATUS_OK);
        }
    }
}

// ----- stop without start 测试 -----
TEST_F(ScannerAbiTest, StopWithoutStart) {
    auto drv = m_devices["Scanner"];
    ASSERT_TRUE(drv != nullptr);

    void* inst = drv->ctor(m_test_service.get(), "stop_without_start_scanner");
    ASSERT_NE(inst, nullptr);

    mc::mutable_dict config = create_test_csr_object();
    mc::dict conn = create_test_connector();

    // 初始化
    if (drv->init(inst, &config, &conn) == STATUS_OK) {
        // 直接停止而不启动应该成功
        status_t stop_ret = drv->stop(inst);
        EXPECT_EQ(stop_ret, STATUS_OK);
    }
}

// ----- 完整生命周期多次循环测试 -----
TEST_F(ScannerAbiTest, FullLifecycleMultipleCycles) {
    auto drv = m_devices["Scanner"];
    ASSERT_TRUE(drv != nullptr);

    void* inst = drv->ctor(m_test_service.get(), "lifecycle_cycles_scanner");
    ASSERT_NE(inst, nullptr);

    mc::mutable_dict config = create_test_csr_object();
    mc::dict conn = create_test_connector();

    // 初始化
    if (drv->init(inst, &config, &conn) == STATUS_OK) {
        // 多次完整生命周期
        for (int i = 0; i < 2; ++i) {
            status_t start_ret = drv->start(inst);
            EXPECT_TRUE(start_ret == STATUS_OK || start_ret == STATUS_ERROR);

            status_t stop_ret = drv->stop(inst);
            EXPECT_EQ(stop_ret, STATUS_OK);
        }
    }
}

} // namespace test
} // namespace scanner
} // namespace drivers